#include "DATManager.h"
#include "XMLManager.h"
#include "HaarLikeDetector.h"
#include "XMLDetector.h"
#include "SIFTTracker.h"
#include "DATSIFTFactory.h"
#include "SIFTTrackerFactory.h"
#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
#include <vector>

#ifdef _DEBUG
//#include "vld.h"
//#define VLD_MAX_DATA_DUMP 30
//#define VLD_MAX_TRACE_FRAMES 0
//#define VLD_AGGREGATE_DUPLICATES 1
#endif

using namespace std;
namespace cv {
	void dottedLine(Mat& inImg,cv::Point inPt1, cv::Point inPt2,cv::Scalar inColor, int inThickness, int inLenghOfDots, int inLineType, bool inLeftToRight);
	void dottedRect(Mat& inImg,cv::Point inPt1, cv::Point inPt2,cv::Scalar inColor, int inThickness, int inLenghOfDots, int inLineType);
	void dottedRect(Mat& inImg,cv::Rect inRect,cv::Scalar inColor, int inThickness, int inLenghOfDots, int inLineType);
};
using namespace cv;

enum StartingMode
{
	eManual = 0,
	eDetectorTest = 1,		
	eMatchTest = 2, 
	eSearchTest = 3, //Used for SEARCH only (Match is a DetectorTest with XMLDetector and 0 for thresholds)
	eAutomatic = 4
};



int main(int argc, char* argv[])
{
	map<string,StartingMode> lStartingModeMap;
	lStartingModeMap["Manual"] = eManual;
	lStartingModeMap["DetectorTest"] = eDetectorTest;
	lStartingModeMap["MatchTest"] = eMatchTest;
	lStartingModeMap["SearchTest"] = eSearchTest;
	lStartingModeMap["Automatic"] = eAutomatic;
	//argc, argv
	/**
		Detector Type("HaarLike"/"XML")
		Detectors Path File("C:\AppDir\DetectorsPathFile.dat")
			Cascade1Path("C:\CascadesDir\Cascade1.xml") Name("Anything") APrioriConfidence(0,1) ScaleFactor(>1) MinNumberOfNeighbors(0,inf) Flipside(0,1)
		Video Path("C:\Data\Video.avi")
		XML Path("C:\Results\Result_Video.xml")
		StartingMode("Manual", "DetectorTest", "TrackingTest", "Automatic")
		StartingFrame(0-EndOfVideo)
		GeneralConfidenceThreshold
		AliveThreshold
		DeadThreshold
	*/
	StartingMode lStartingMode = eManual;
	int lStartFrame = 0;
	double lGeneralConfidenceThreshold = 0.9;
	int lAliveThreshold = 5;
	float lDeadThreshold = 5;
	if(argc<5 || argc>10)
	{
		std::cerr<<"Arguments not okay !"<<std::endl;
		std::cerr<<"Usage:"<<std::endl;
		std::cerr<<"DATManagerTest.exe DetectorType DetectorPathFile VideoPath XMLPath"<<std::endl;
		std::cerr<<"DetectorType(\"HaarLike\"/\"XML\")"<<std::endl;
		std::cerr<<"DetectorPathFile(\"C:/AppDir/DetectorsPathFile.dat\")"<<std::endl;
		std::cerr<<"\t Cascade1Path(\"C:/CascadesDir/Cascade1.xml\") Name(\"Anything\") APrioriConfidence(0,1) ScaleFactor(>1) MinNumberOfNeighbors(0,inf) Flipside(0,1)"<<std::endl;
		std::cerr<<"or"<<std::endl;
		std::cerr<<"\t XML1Path(\"C:/GroundTruth/SeqXGroundTruth.xml\") Name(\"Anything\")"<<std::endl;
		std::cerr<<"VideoPath(\"C:/Data/Video.avi\")"<<std::endl;
		std::cerr<<"XMLPath(\"C:/Results/Result_Video.xml\")"<<std::endl;
		std::cerr<<"StartingMode(\"Manual\", \"DetectorTest\", \"TrackingTest\", \"Automatic\")"<<std::endl;
		std::cerr<<"StartingFrame(0,EndOfVideo)"<<std::endl;
		std::cerr<<"GeneralConfidenceThreshold(0,1)"<<std::endl;
		std::cerr<<"AliveThreshold(0-)"<<std::endl;
		std::cerr<<"DeadThreshold(0-)"<<std::endl;
		system("pause");
		return -1;
	}
	if(argc>=6)
		lStartingMode = lStartingModeMap[argv[5]];
	if(argc>=7)
		lStartFrame = atoi(argv[6]);
	if(argc>=8)
		lGeneralConfidenceThreshold = atof(argv[7]);
	if(argc>=9)
		lAliveThreshold = atoi(argv[8]);
	if(argc>=10)
		lDeadThreshold = (float)atof(argv[9]);

	cout<<"Initialize DATManager."<<endl;
	//cout<<"Number of Threads : "<< cvGetNumThreads() <<"."<<endl;
	DATManager* lDATManager = new DATManager(lGeneralConfidenceThreshold,lAliveThreshold,lDeadThreshold);
	lDATManager->installDATFactory(new DATSIFTFactory);
	lDATManager->installTrackerFactory(new SIFTTrackerFactory);
	cout<<"=============Done============="<<endl<<endl;

	if(string(argv[1])=="HaarLike")
	{
		cout<<"Initialize HaarLikeDetector."<<endl;
		ifstream lCascadePathFile(argv[2]);
		if(lCascadePathFile.fail())
		{
			std::cerr<<"CascadePathFile not okay !"<<std::endl;
			system("pause");
			return -3;
		}
		while(!lCascadePathFile.eof())
		{
			string lCascadePath;
			string lCascadeName;
			double lAPrioriConfidence;
			double lScaleFactor;
			int lMinNbNeighbors;
			bool lFlipside;

			lCascadePathFile>>lCascadePath;
			lCascadePathFile>>lCascadeName;
			lCascadePathFile>>lAPrioriConfidence;
			lCascadePathFile>>lScaleFactor;
			lCascadePathFile>>lMinNbNeighbors;
			lCascadePathFile>>lFlipside;
	
			//Temporarly : max size == [220 180]
			//Size lMaxSize;
			//if(lCascadeName == "LSide" || lCascadeName == "RSide")
			//	lMaxSize = Size(180,90);
			//else
			//	lMaxSize = Size(180,150);

			HaarLikeDetector* lHLDetector = new HaarLikeDetector(lCascadePath,lCascadeName,lAPrioriConfidence,lScaleFactor,lMinNbNeighbors,0,Size(),Size(),lFlipside);
			if(!lHLDetector->isOk())
			{
				cerr<<"Bad cascade: "<<lCascadePath<<endl;
				system("pause");
				return -4;
			}
			lDATManager->addDetector(lHLDetector);
		}
	}
	else if(string(argv[1])=="XML")
	{
		cout<<"Initialize XMLDetector."<<endl;
		ifstream lXMLPathFile(argv[2]);
		if(lXMLPathFile.fail())
		{
			std::cerr<<"XMLDetector not okay !"<<std::endl;
			system("pause");
			return -3;
		}
		while(!lXMLPathFile.eof())
		{
			string lXMLPath;
			string lDetectorName;
			int lNbOfJump = 0;
			lXMLPathFile>>lXMLPath;
			lXMLPathFile>>lDetectorName;
			//int lPos = lXMLPathFile.tellg();
			lXMLPathFile.seekg(1,ios::cur);
			char lJump = lXMLPathFile.peek();
			if(lJump >= '0' && lJump <= '9')
				lXMLPathFile>>lNbOfJump;
			//else
			//	lXMLPathFile.seekg(-1,ios::cur);
			XMLDetector* lXMLDetector = new XMLDetector(lDetectorName);
			lXMLDetector->setJumpFrame(lNbOfJump);
			if(!lXMLDetector->createXMLDoc(lXMLPath))
			{
				cerr<<"Bad XML: "<<lXMLPath<<endl;
				system("pause");
				return -4;
			}
			if(lStartFrame != 0)
				if(!lXMLDetector->setFrame(lStartFrame))
				{
					cerr<<"The XML doesnt have the frame: "<<lStartFrame<<endl;
					system("pause");
					return -4;					
				}

			lDATManager->addDetector(lXMLDetector);
		}
		cout<<"Desactivate triming since the XML detector is \"perfect\""<<endl;
		lDATManager->changeTrimEnabled();
	}
	else
	{
		cerr<<"Bad argument DetectorType: "<<argv[1]<<endl;
		system("pause");
		return -2;
	}
	map<string,CvScalar> lColors;
	lColors["RSide"] = CV_RGB(255.0,0,0);
	lColors["LSide"] = CV_RGB(255.0,255.0,0);
	lColors["Rear"] = CV_RGB(0,0,255.0);
	lColors["Front"] = CV_RGB(0,255.0,0);
	cout<<"=============Done============="<<endl;

	string lVideoPath = argv[3];
	string lVideoName = lVideoPath.substr(0,lVideoPath.find_last_of('.'))+"_DAT.avi";
	cout<<"Initialize VideoFeed "<<lVideoPath<<"."<<endl;
	if(!lDATManager->addVideoFeed(lVideoPath))
	{
		cerr<<"Video feed error."<<endl;
		system("pause");
		return -5;
	}
	cout<<"=============Done============="<<endl<<endl;

	cout<<"Initialize XMLManager."<<endl;
	string lXMLPath = argv[4];
	bool lXMLOk = false;
	XMLManager* lXMLManager = new XMLManager;
	lXMLOk = lXMLManager->openFile(lXMLPath,false);
	if(!lXMLOk)
	{
		cerr<<"XML open file error."<<endl;
		system("pause");
		return -6;
	}
	lXMLOk = lXMLManager->init(lDATManager->getVideoFeed()->getNumFrames());
	if(!lXMLOk)
	{
		cerr<<"XML init error."<<endl;
		system("pause");
		return -6;
	}
	lDATManager->installXMLManager(lXMLManager);
	cout<<"=============Done============="<<endl<<endl;

	//best group
	//string lCascadeName1 = "D:/Usagers/matre697/Maitrise/HaarTraining/colosse_opencv220/side/side_n6195(2065)_p6000(634)_x02_y02_z02_dev25_w36_h12_nst19_nsp1_mhr09995_mfa04_wt09.xml";	//sf105
	//string lCascadeName2 = "D:/Usagers/matre697/Maitrise/HaarTraining/colosse_opencv220/rear/rear_n6195(2065)_p6000(858)_x005_y005_z005_dev25_w22_h18_nst15_nsp1_mhr09995_mfa03_wt09.xml"; //sf110
	//string lCascadeName3 = "D:/Usagers/matre697/Maitrise/HaarTraining/colosse_opencv220/front/front_n6195(2065)_p6000(598)_x005_y005_z005_dev25_w22_h18_nst19_nsp1_mhr09995_mfa04_wt09.xml"; //sf105

	//string lVideoPath = "D:/Usagers/matre697/Data.nobkp/Benchmark_2.avi";												//sequence 1
	//string lVideoPath = "E:/Videos.nobkp/RAW/a21p2s13v06T001C1_6940_7940_b18_c106.avi_radialDistCorr0.0000014.avi";	//sequence 2
	//string lVideoPath = "E:/Videos.nobkp/RAW/a21p2s14v06T001C1_29470_30890.avi_radialDistCorr0.0000013.avi";			//sequence 3	
	//string lVideoPath = "E:/Videos.nobkp/Andre/RAW/VID00109_1800_2800.avi";											//Sequence HighRes 1
	//string lVideoPath = "E:/Videos.nobkp/Andre/RAW/VID00110_0_900.avi";												//Sequence HighRes 2
	//string lVideoPath = "E:/Videos.nobkp/Andre/RAW/VID00112_0_ 900.avi";												//Sequence HighRes 3	//1
	//string lVideoPath = "E:/Videos.nobkp/Andre/RAW/VID00113_3150_ 4050.avi";											//Sequence HighRes 4
	//string lVideoPath = "E:/Videos.nobkp/Andre/RAW/VID00115_915_ 1998.avi";											//Sequence HighRes 5	//2
	
	bool lEnd = false;
	bool lSaveVideo = false;
	bool lNoError = false;
	VideoWriter lVideoSequence;
	list<DATObject*> lDetections;
	list<Tracker*> lUpdatedTrackers;
	CvPoint lPt1,lPt2;

	if(!lDATManager->isReady())
	{
		cerr<<"Something in DATManager is not initialized correctly."<<endl;
		system("pause");
		return -7;
	}

	int lLastFrame = lDATManager->getVideoFeed()->getNumFrames();

	bool lWaitForIt = true;
	bool lShowIt = true; //in milli
	bool lDoMatching = true;
	
	switch(lStartingMode)
	{
	case eManual:
		//lDATManager->changePredictionEnabled(); //For try
		break;
	case eDetectorTest:
		lDATManager->changeDetectionEnabled();
		lWaitForIt = false;
		lDATManager->changeXMLSaveIn();
		lShowIt = false;
		break;
	case eMatchTest:
		//Not supported yet
		lDATManager->changeDetectionEnabled();
		lDATManager->changeTrackingEnabled();
		lDATManager->changeMergingEnabled();
		lDATManager->setDoSearch(false);
		lWaitForIt = false;
		lDATManager->changeXMLSaveIn();
		lShowIt = false;
		break;
	case eSearchTest:
		//Not supported yet
		lDATManager->changeDetectionEnabled();
		lDATManager->changeTrackingEnabled();
		lDATManager->changeMergingEnabled();
		//lDATManager->changePredictionEnabled();
		lDATManager->setDoMatching(false);
		lWaitForIt = false;
		lDATManager->changeXMLSaveIn();
		lShowIt = false;
		break;
	case eAutomatic:
		lDATManager->changeDetectionEnabled();
		lDATManager->changeTrackingEnabled();
		lWaitForIt = false;
		lDATManager->changeXMLSaveIn();
		lShowIt = false;
		break;
	}

	for(int i=lStartFrame;(!lEnd)&&i<lDATManager->getVideoFeed()->getNumFrames()&&i<lLastFrame;)
	{
		cout<<"Frame "<<i<<": ";
		cout<<"Detect = "<<lDATManager->getDetectionEnabled()<<",";
		cout<<"Trim = "<<lDATManager->getTrimEnabled()<<",";
		cout<<"Track = "<<lDATManager->getTrackingEnabled()<<",";
		cout<<"Predict = "<<lDATManager->getPredictionEnabled()<<",";
		cout<<"SaveXML = "<<lDATManager->getXMLSaveIn()<<"."<<endl;

		lNoError = lDATManager->start(lDetections,lUpdatedTrackers,i);
		if(!lNoError)
		{
			cerr<<"Something went wrong... I hope you've received another error hint..."<<endl;
			system("pause");
			return -8;
		}

		//remove the freaking bottom of the screen
		//cvSetImageROI(lDATManager->getVideoFeed()->getImage(), cvRect(0, 0, lDATManager->getVideoFeed()->getImage()->width, 390));
		Mat lShowedImage = 	lDATManager->getVideoFeed()->getImage();
		

		//Show me everything you've got in detection!
		if(lDATManager->getDetectionEnabled()&&!lDATManager->getTrackingEnabled())
		{
			for(list<DATObject*>::iterator lIter=lDetections.begin(); lIter != lDetections.end(); ++lIter)
			{
				lPt1.x = (*lIter)->mLastPosition.x;
				lPt2.x = ((*lIter)->mLastPosition.x+(*lIter)->mLastPosition.width);
				lPt1.y = (*lIter)->mLastPosition.y;
				lPt2.y = ((*lIter)->mLastPosition.y+(*lIter)->mLastPosition.height);

				cv::rectangle(lShowedImage,lPt1,lPt2,lColors[(*lIter)->mLastObjectType]);

				cv::Point lPtText(lPt1);
				lPtText.x += (*lIter)->mLastPosition.width/2 - 2;
				lPtText.y += (*lIter)->mLastPosition.height/2 - 2;
				ostringstream lIDConv;
				lIDConv<<(*lIter)->mID;
				cv::putText(lShowedImage,lIDConv.str(),lPtText,FONT_HERSHEY_SIMPLEX,0.5,lColors[(*lIter)->mLastObjectType],2);
			}
		}
		if(lDATManager->getDetectionEnabled()&&lDATManager->getTrackingEnabled())
		{
			//Debug tool (check if 2 object with same ID)
			for(list<Tracker*>::iterator lIter=lUpdatedTrackers.begin(); lIter != lUpdatedTrackers.end(); ++lIter)
			{
				for(list<Tracker*>::iterator lIter2=lIter; lIter2 != lUpdatedTrackers.end(); ++lIter2)
				{
					if(lIter==lIter2)
						continue;
					if((*lIter)->getID() == (*lIter2)->getID())
					{
						cerr<<"Ok, 2 object with the same ID: "<<(*lIter)->getID();
						system("pause");
					}
				}
			}
			//End debug

			for(list<Tracker*>::iterator lIter=lUpdatedTrackers.begin(); lIter != lUpdatedTrackers.end(); ++lIter)
			{
				lPt1.x = (*lIter)->getLastSeenDATObject()->mLastPosition.x;
				lPt2.x = ((*lIter)->getLastSeenDATObject()->mLastPosition.x+(*lIter)->getLastSeenDATObject()->mLastPosition.width);
				lPt1.y = (*lIter)->getLastSeenDATObject()->mLastPosition.y;
				lPt2.y = ((*lIter)->getLastSeenDATObject()->mLastPosition.y+(*lIter)->getLastSeenDATObject()->mLastPosition.height);

				//bool lCrapH = (*lIter)->getLastSeenDATObject()->mLastPosition.height<10;
				//bool lCrapW = (*lIter)->getLastSeenDATObject()->mLastPosition.width<10;
				//if(!lCrapH && !lCrapW)
				//{
				cv::Point lPtText(lPt1);
				lPtText.x += (*lIter)->getLastSeenDATObject()->mLastPosition.width/2 - 2;
				lPtText.y += (*lIter)->getLastSeenDATObject()->mLastPosition.height/2 - 2;
				ostringstream lIDConv;
				lIDConv<<(*lIter)->getID();
				cv::putText(lShowedImage,lIDConv.str(),lPtText,FONT_HERSHEY_SIMPLEX,0.5,lColors[(*lIter)->getLastSeenDATObject()->mLastObjectType],2);
				//}

				//if detected --> show full line rect
				if((*lIter)->getLastSeenDATObject()->mLastWasDetected)
					cv::rectangle(lShowedImage,lPt1,lPt2,lColors[(*lIter)->getLastSeenDATObject()->mLastObjectType]);
			
				lPt1.x = lPt1.x - 1 ;
				lPt2.x = lPt2.x + 1;
				lPt1.y = lPt1.y - 1;
				lPt2.y = lPt2.y + 1;

				//if hard tracked --> show line (- - -) 1 pixel + loin
				if((*lIter)->getLastWasTracked()==1)
				{
					cv::dottedRect(lShowedImage,lPt1,lPt2,lColors[(*lIter)->getLastSeenDATObject()->mLastObjectType],1,3,8);
				}
				//if soft tracked --> show line (--  --  --) 1 pixel + loin
				if((*lIter)->getLastWasTracked()==2)
				{
					cv::dottedRect(lShowedImage,lPt1,lPt2,lColors[(*lIter)->getLastSeenDATObject()->mLastObjectType],1,6,8);
				}
				
			}			
		}
		if(lWaitForIt)
		{
			imshow( "Video", lShowedImage );

			char key = cvWaitKey(0);
			if(key == 'p')
			{
				lWaitForIt = false;
			}
			if(key == 's')
			{
				//save
				stringstream lTemp;
				lTemp << i;
				string lNewFilename = lVideoName+"_"+lTemp.str()+".bmp";
				imwrite(lNewFilename.c_str(),lShowedImage);
			}
			if(key == 'h')
				lDATManager->changeDetectionEnabled();
			if(key == 't')
			{
				lDATManager->changeTrackingEnabled();
				//Should delete every vector if cancel tracking
				//lDATManager->clear();
			}
			if(key == 'S')
			{
				
				lSaveVideo = !lSaveVideo;
				if(lSaveVideo)
				{	//open new
					stringstream lTemp;
					lTemp << i;
					string lNewFilename = lVideoName+"_beginAtFrame_"+lTemp.str()+".avi";
					lVideoSequence.open(lNewFilename.c_str(),0,lDATManager->getVideoFeed()->getFPS(),cv::Size(lShowedImage.cols,lShowedImage.rows));
				}
				else
				{	//close
					if(lVideoSequence.isOpened())
					{
						//lVideoSequence.release();
						lVideoSequence = VideoWriter();
					}
				}
			}
			if(key == 'a')
			{
				if(i>0)
					i--;
			}
			if(key == 'd')
			{
				i++;
			}
			if(key == 'q')
			{
				i=i-10;
				if(i<0)
					i=0;
			}
			if(key =='e')
			{
				i = i+10;
			}
			if(key == 27)
			{
				//if(lVideoSequence)
				//	cvReleaseVideoWriter(&lVideoSequence);
				lEnd = true;
			}
			if(key =='x')
			{
				lDATManager->changeXMLSaveIn();
			}
		}
		else
		{
			if(lShowIt)
			{
				imshow( "Video", lShowedImage );
				char key = waitKey(1000);
				
				if(key=='p')
					lWaitForIt = true;
				else
					i++;
			}
			else
				i++;
		}
		//cvSetImageROI(lDATManager->getVideoFeed()->getImage(), cvRect(0, 0, lDATManager->getVideoFeed()->getImage()->width, lDATManager->getVideoFeed()->getImage()->height));

		if(lSaveVideo && lVideoSequence.isOpened())
		{
			lVideoSequence.write(lShowedImage);
		}

		if(!lDATManager->getTrackingEnabled())
		{
			for(list<DATObject*>::iterator lIter=lDetections.begin(); lIter != lDetections.end(); ++lIter)
			{
				delete (*lIter);
			}
		}
		lDetections.clear();
		lUpdatedTrackers.clear();
	}
	if(lVideoSequence.isOpened())
	{
		//lVideoSequence.release();
		lVideoSequence = VideoWriter();
	}
	destroyWindow( "Video" );
	delete lDATManager;
	return 0;
}

void cv::dottedLine(Mat& inImg,cv::Point inPt1, cv::Point inPt2,cv::Scalar inColor, int inThickness, int inLenghOfDots, int inLineType, bool inLeftToRight)
{
	cv::LineIterator lIterator( inImg, inPt1, inPt2, inLineType, inLeftToRight );
	int lCount = lIterator.count;
	int offset,x,y;


	for( int i = 0; i < lCount; i= i + (inLenghOfDots*2-1) )
	{
		if(i+inLenghOfDots > lCount)
			break;

		offset = lIterator.ptr - (uchar*)(inImg.data);
        y = offset/inImg.step;
		x = (offset - y*inImg.step)/(3*sizeof(uchar) /* size of pixel */);

		cv::Point lTemp1(x,y);
		for(int j=0;j<inLenghOfDots-1;j++)	//I want to know have the last of these in the iterator
			lIterator++;

        offset = lIterator.ptr - (uchar*)(inImg.data);
        y = offset/inImg.step;
        x = (offset - y*inImg.step)/(3*sizeof(uchar) /* size of pixel */);

		cv::Point lTemp2 = cvPoint(x,y);
		cv::line(inImg,lTemp1,lTemp2,inColor,inThickness,inLineType);
		for(int j=0;j<inLenghOfDots;j++)
			lIterator++;
	}
}

void cv::dottedRect(Mat& inImg,cv::Point inPt1, cv::Point inPt2,cv::Scalar inColor, int inThickness, int inLenghOfDots, int inLineType)
{	//1---2
	//|	  |
	//4---3
	cv::Point lTempPt1(inPt2.x,inPt1.y);
	cv::Point lTempPt2(inPt1.x,inPt2.y);
	cv::dottedLine(inImg,inPt1,lTempPt1,inColor,inThickness,inLenghOfDots,inLineType, true);
	cv::dottedLine(inImg,lTempPt1,inPt2,inColor,inThickness,inLenghOfDots,inLineType, true);
	cv::dottedLine(inImg,inPt2,lTempPt2,inColor,inThickness,inLenghOfDots,inLineType, false);
	cv::dottedLine(inImg,lTempPt2,inPt1,inColor,inThickness,inLenghOfDots,inLineType, false);
}

void cv::dottedRect(Mat& inImg,cv::Rect inRect,cv::Scalar inColor, int inThickness, int inLenghOfDots, int inLineType)
{	//1---2
	//|	  |
	//4---3
	cv::Point lPt1 = cv::Point(inRect.x,inRect.y);
	cv::Point lPt2 = cv::Point(inRect.x+inRect.width,inRect.y);
	cv::Point lPt3 = cv::Point(inRect.x+inRect.width,inRect.y+inRect.height);
	cv::Point lPt4 = cv::Point(inRect.x,inRect.y+inRect.height);

	cv::dottedLine(inImg,lPt1,lPt2,inColor,inThickness,inLenghOfDots,inLineType, true);
	cv::dottedLine(inImg,lPt2,lPt3,inColor,inThickness,inLenghOfDots,inLineType, true);
	cv::dottedLine(inImg,lPt3,lPt4,inColor,inThickness,inLenghOfDots,inLineType, false);
	cv::dottedLine(inImg,lPt4,lPt1,inColor,inThickness,inLenghOfDots,inLineType, false);
}